

#include <QtWidgets>

#include "dbusargvitem.hpp"
#include "dbusargvmodel.hpp"

DBusArgvModel::DBusArgvModel(const QStringList &names, const QList<int> &args, QObject *parent)
{
    rootItem = new DBusArgvItem(names,args);
}

DBusArgvModel::DBusArgvModel(const QStringList &names, const QStringList &args, QObject *parent)
    : QAbstractItemModel(parent)
{
    rootItem = new DBusArgvItem(names,args);
}

DBusArgvModel::DBusArgvModel(const QStringList &names, const QList<DVariant> values, QObject *parent)
{
     rootItem = new DBusArgvItem(names,values);
}
DBusArgvModel::~DBusArgvModel()
{
    delete rootItem;
}

QList<DVariant> DBusArgvModel::getArgs(bool *ok)
{
    return rootItem->getArgs (ok);
}
int DBusArgvModel::columnCount(const QModelIndex & /* parent */) const
{
    return rootItem->columnCount();
}
QVariant DBusArgvModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid())
        return QVariant();

    DBusArgvItem *item = getItem(index);
    if (role == Qt::CheckStateRole)
    {
        if(index.column ()==2)
        {
            if(item->getValueType()==QMetaType::Bool)
            {
                return item->m_value.toBool ()?Qt::Checked :Qt::Unchecked;
            }
        }
    }
    if (role != Qt::DisplayRole && role != Qt::EditRole)
        return QVariant();

    if(index.column ()==2)
    {
        if(item->getValueType()==QMetaType::Bool)
        {
            return QVariant();
        }
    }
    if(index.column ()==3)
    {
        if(item->m_showModel == ShowModelDefault)
        {
            return "Default";
        }else if(item->m_showModel == ShowModelDec)
        {
            return "Dec";
        }else if(item->m_showModel == ShowModelHex)
        {
            return "Hex";
        }
    }
    return item->data(index.column ());
}
bool DBusArgvModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    DBusArgvItem *Item = getItem(index);
    if (role == Qt::CheckStateRole)
    {
        if(Item!=Q_NULLPTR)
        {
            if(Item->getValueType () == QMetaType::Bool)
            {
                if(value.toInt () == Qt::Checked)
                {
                    Item->setValue (QVariant(true));
                }else
                {
                    Item->setValue (QVariant(false));
                }
                emit commitModelData(this,index);
                return true;
            }
        }
    }

    if(role!=Qt::EditRole)
    {
        return QAbstractItemModel::setData(index,value,role);
    }
    if(Item!=Q_NULLPTR)
    {
        if(index.column () ==2)
        {
            QVariant tmp = value;
           bool b =  tmp.convert(Item->getValueType ());
            if(b)
            {
                Item->setValue(tmp);
                int from,to;
                if(Item->adjustItem (from,to)>=0)
                {
                    beginInsertRows (index.parent (),from,to);
                    endInsertRows ();
                }
                emit commitModelData(this,index);
                return true;
            }
        }else if(index.column () == 3)
        {
            Item->m_showModel = (ShowModel)value.toInt ();
            emit commitModelData(this,index);
        }
    }
    return false;

}
Qt::ItemFlags DBusArgvModel::flags(const QModelIndex &index) const
{
    if (!index.isValid())
        return 0;
    if (index.isValid()) {
        if(index.column () >1)
        {
            DBusArgvItem *item = static_cast<DBusArgvItem*>(index.internalPointer());
            if (item)
            {
                if(item->getValueType()<QMetaType::User)
                {
                    Qt::ItemFlags flags =  Qt::ItemIsEditable| QAbstractItemModel::flags(index);
                    if(item->getValueType()==QMetaType::Bool)
                    {
                        flags = Qt::ItemIsUserCheckable | flags;
                    }
                    return  flags;
                }
            }
        }
    }
    return QAbstractItemModel::flags(index);

}
DBusArgvItem *DBusArgvModel::getItem(const QModelIndex &index) const
{
    if (index.isValid()) {
        DBusArgvItem *item = static_cast<DBusArgvItem*>(index.internalPointer());
        if (item)
            return item;
    }
    return rootItem;
}

QVariant DBusArgvModel::headerData(int section, Qt::Orientation orientation,
                               int role) const
{
    if (orientation == Qt::Horizontal && role == Qt::DisplayRole)
    {
        return rootItem->data(section);
    }

    return QVariant();
}
QModelIndex DBusArgvModel::index(int row, int column, const QModelIndex &parent) const
{
    if (parent.isValid() && parent.column() != 0)
        return QModelIndex();
    DBusArgvItem *parentItem = getItem(parent);

    DBusArgvItem *childItem = parentItem->child(row);
    if (childItem)
        return createIndex(row, column, childItem);
    else
        return QModelIndex();
}


bool DBusArgvModel::insertRows(int position, int rows, const QModelIndex &parent)
{
    DBusArgvItem *parentItem = getItem(parent);
    bool success;
    if(parentItem->getValueType () == DBUS_TYPE_ARRAR)
    {      QString strArgs = parentItem->getArraySubArgType ();
        if(!strArgs.isEmpty ())
        {
            beginInsertRows(parent, position, position + rows - 1);
            DBusArgvItem *items  = new DBusArgvItem("", strArgs, parentItem,DBUS_TYPE_ARRAR);
            parentItem->childItems.insert (position+1,items);
            endInsertRows();
        }
    }else if(parentItem->getValueType () == DBUS_TYPE_DICT)
    {
        QString keyArgs = parentItem->getDictKeyArgType ();
        QString valueArgs = parentItem->getDictValueArgType ();
        if(!keyArgs.isEmpty () && !valueArgs.isEmpty ())
        {
            beginInsertRows(parent, position, position + 2 - 1);
            DBusArgvItem *itemk  = new DBusArgvItem("", keyArgs, parentItem,DBUS_TYPE_DICT);
            DBusArgvItem *itemv  = new DBusArgvItem("", valueArgs, parentItem,DBUS_TYPE_DICT);
            parentItem->childItems.insert (position+2,itemk);
            parentItem->childItems.insert (position+3,itemv);

            endInsertRows();
        }
    }

    return success;
}

//! [7]
QModelIndex DBusArgvModel::parent(const QModelIndex &index) const
{
    if (!index.isValid())
        return QModelIndex();

    DBusArgvItem *childItem = getItem(index);
    DBusArgvItem *parentItem = childItem->parent();

    if (parentItem == rootItem)
        return QModelIndex();

    return createIndex(parentItem->childNumber(), 0, parentItem);
}
//! [7]

bool DBusArgvModel::removeColumns(int position, int columns, const QModelIndex &parent)
{
    return false;
}

bool DBusArgvModel::removeRows(int position, int rows, const QModelIndex &parent)
{
    DBusArgvItem *parentItem = getItem(parent);
    bool success = true;
    DBusArgvItem *Item = parentItem->childItems.at (position);
    if(Item->m_parenttype == DBUS_TYPE_ARRAR)
    {
        if(parentItem->childItems.count () <2)
        {
            return false;
        }else
        {
            beginRemoveRows(parent, position, position);
            parentItem->childItems.removeAt (position);
            endRemoveRows();
            return true;
        }
    }else if(Item->m_parenttype == DBUS_TYPE_DICT)
    {
        if(parentItem->childItems.count () <4)
        {
            return false;
        }else
        {
            if(position%2 ==1)
            {
                position = position-1;
            }
            beginRemoveRows(parent, position, position+1);
            parentItem->childItems.removeAt (position+1);
            parentItem->childItems.removeAt (position);
            endRemoveRows();
            return true;
        }

    }
    return false;
}

bool DBusArgvModel::moveRows(const QModelIndex &sourceParent, int srcRow, int count, const QModelIndex &destinationParent, int dstRow)
{
    if(sourceParent!= destinationParent)
    {
        return false;
    }
    DBusArgvItem *parentItem = this->getItem (sourceParent);
    if (srcRow == dstRow
        || srcRow < 0 || srcRow >= parentItem->childItems.count()
        || dstRow < 0 || dstRow > parentItem->childItems.count())
    {
        return false;
    }
    if(srcRow<dstRow)
    {
        if (!beginMoveRows(sourceParent, srcRow, srcRow, destinationParent, dstRow+1))
        {
            return false;
        }
    }else
    {
        if (!beginMoveRows(sourceParent, srcRow, srcRow+1, destinationParent, dstRow))
        {
            return false;
        }
    }
    if(dstRow>=parentItem->childItems.count ())
    {
        dstRow = parentItem->childItems.count ()-1;
    }else if(dstRow<0)
    {
        dstRow = 0;
    }
    parentItem->childItems.move (srcRow,dstRow);
    endMoveRows ();
    return true;
}
//#define DBUS_TYPE_STRUCT QMetaType::User+2001
//#define DBUS_TYPE_DICT   QMetaType::User+2002
//#define DBUS_TYPE_ARRAR  QMetaType::User+2003

//void DBusArgvModel::commitModelData(QAbstractItemModel *model, const QModelIndex &index) const
//{
//    DBusArgvItem *Item = getItem(index);
//    QModelIndex parentIndex = index;
//    while (Item->getLevel () != LEVEL_TOP) {
//        parentIndex = parentIndex.parent ();
//        Item = getItem(parentIndex);

//        QStringList textsubs;
//        QList<DBusArgvItem *> subs = Item->getChildItems();
//        for(int i=0;i<subs.count ();i++)
//        {
//            textsubs.append (subs.at (i)->getValue ().toString ());
//        }
//        QString text="";
//        if(DBUS_TYPE_STRUCT == Item->getValueType ())
//        {
//            text = "("+textsubs.join (',')+")";
//        }else if(DBUS_TYPE_DICT == Item->getValueType ())
//        {
//            text = "{"+textsubs.join (',')+"}";
//        }else if(DBUS_TYPE_ARRAR == Item->getValueType ())
//        {
//            text = "["+textsubs.join (',')+"]";
//        }else
//        {
//            text = "\""+textsubs.join (',')+"\"";
//        }
//        Item->setValue (text);
//        model->setData(parentIndex, text, Qt::DisplayRole);
//    }
//}
int DBusArgvModel::rowCount(const QModelIndex &parent) const
{
    DBusArgvItem *parentItem = getItem(parent);

    return parentItem->childCount();
}

//bool DBusArgvModel::setData(const QModelIndex &index, const QVariant &value, int role)
//{
//    if (role != Qt::EditRole)
//        return false;

//    DBusArgvItem *item = getItem(index);
//    bool result = item->setData(index.column(), value);

//    if (result)
//        emit dataChanged(index, index);

//    return result;
//}

//bool DBusArgvModel::setHeaderData(int section, Qt::Orientation orientation,
//                              const QVariant &value, int role)
//{
//    if (role != Qt::EditRole || orientation != Qt::Horizontal)
//        return false;

//    bool result = rootItem->setData(section, value);

//    if (result)
//        emit headerDataChanged(orientation, section, section);

//    return result;
//}

//void DBusArgvModel::setupModelData(const QStringList &lines, DBusArgvItem *parent)
//{
//    QList<DBusArgvItem*> parents;
//    QList<int> indentations;
//    parents << parent;
//    indentations << 0;

//    int number = 0;

//    while (number < lines.count()) {
//        int position = 0;
//        while (position < lines[number].length()) {
//            if (lines[number].at(position) != ' ')
//                break;
//            ++position;
//        }

//        QString lineData = lines[number].mid(position).trimmed();

//        if (!lineData.isEmpty()) {
//            // Read the column data from the rest of the line.
//            QStringList columnStrings = lineData.split("\t", QString::SkipEmptyParts);
//            QVector<QVariant> columnData;
//            for (int column = 0; column < columnStrings.count(); ++column)
//                columnData << columnStrings[column];

//            if (position > indentations.last()) {
//                // The last child of the current parent is now the new parent
//                // unless the current parent has no children.

//                if (parents.last()->childCount() > 0) {
//                    parents << parents.last()->child(parents.last()->childCount()-1);
//                    indentations << position;
//                }
//            } else {
//                while (position < indentations.last() && parents.count() > 0) {
//                    parents.pop_back();
//                    indentations.pop_back();
//                }
//            }

//            // Append a new item to the current parent's list of children.
//            DBusArgvItem *parent = parents.last();
//            parent->insertChildren(parent->childCount(), 1, rootItem->columnCount());
//            for (int column = 0; column < columnData.size(); ++column)
//                parent->child(parent->childCount() - 1)->setData(column, columnData[column]);
//        }

//        ++number;
//    }
//}
